package com.ecarx.camera.worker.camera.dvr;

import com.ecarx.camera.constant.Constants;
import com.ecarx.camera.utils.LogUtils;
import com.ecarx.camera.worker.camera.timer.RecordingTimerHelper;
import com.ecarx.camera.worker.config.ConfigManager;
import com.ecarx.camera.worker.event.DvrEvent;
import com.jeremyliao.liveeventbus.LiveEventBus;

/**
 * Dvr后台监听
 */
public class DvrMonitor {

    private static final String TAG = "DvrMonitor";

    private final IDvrAPI.IOperateResultsWatcher mOperateResultWatcher = new IDvrAPI.IOperateResultsWatcher() {

        @Override
        public void onDvrCaptureInProgress() {
            LogUtils.d(TAG, "operate_callback: onDvrCaptureInProgress");
        }

        @Override
        public void onDvrCaptureSuccess() {
            LogUtils.d(TAG, "operate_callback: onDvrCaptureSuccess");
            LiveEventBus.get(DvrEvent.CaptureResultEvent.class).post(new DvrEvent.CaptureResultEvent(true));
        }

        @Override
        public void onDvrCaptureFail() {
            LogUtils.d(TAG, "operate_callback: onDvrCaptureFail");
            LiveEventBus.get(DvrEvent.CaptureResultEvent.class).post(new DvrEvent.CaptureResultEvent(false));
            // TODO: 2023/2/7 拍照失败时是否需要提示？
        }

        @Override
        public void onDvrGeneralRecordInProgress() {
            LogUtils.d(TAG, "operate_callback: onDvrGeneralRecordInProgress");
        }

        @Override
        public void onDvrGeneralRecordSuccess() {
            LogUtils.d(TAG, "operate_callback: onDvrGeneralRecordSuccess");
        }

        @Override
        public void onDvrGeneralRecordFail() {
            LogUtils.d(TAG, "operate_callback: onDvrGeneralRecordFail");
            doOnRecordFinished(Constants.DvrRecordingType.GENERAL, false);
            // TODO: 2023/6/14 录像失败时是否需要提示？
        }

        @Override
        public void onDvrPauseGeneralRecordInProgress() {
            LogUtils.d(TAG, "operate_callback: onDvrPauseGeneralRecordInProgress");
        }

        @Override
        public void onDvrPauseGeneralRecordSuccess() {
            LogUtils.d(TAG, "operate_callback: onDvrPauseGeneralRecordSuccess");
        }

        @Override
        public void onDvrPauseGeneralRecordFail() {
            LogUtils.d(TAG, "operate_callback: onDvrPauseGeneralRecordFail");
        }

        @Override
        public void onDvrEmergencyRecordInProgress() {
            LogUtils.d(TAG, "operate_callback: onDvrEmergencyRecordInProgress");
        }

        @Override
        public void onDvrEmergencyRecordSuccess() {
            LogUtils.d(TAG, "operate_callback: onDvrEmergencyRecordSuccess");
        }

        @Override
        public void onDvrEmergencyRecordFail() {
            LogUtils.d(TAG, "operate_callback: onDvrEmergencyRecordFail");
            doOnRecordFinished(Constants.DvrRecordingType.EMERGENCY, false);
            // TODO: 2023/6/14 紧急录像失败时是否需要提示？
        }

        @Override
        public void onFactoryResetInProgress() {
            LogUtils.d(TAG, "operate_callback: onFactoryResetting");
        }

        @Override
        public void onFactoryResetSuccess() {
            LogUtils.d(TAG, "operate_callback: onFactoryResetSuccess");
        }

        @Override
        public void onFactoryResetFail() {
            LogUtils.d(TAG, "operate_callback: onFactoryResetFail");
        }

        @Override
        public void onSdcardFormatInProgress() {
            LogUtils.d(TAG, "operate_callback: onSdcardFormatting");
        }

        @Override
        public void onSdcardFormatSuccess() {
            LogUtils.d(TAG, "operate_callback: onSdcardFormatSuccess");
        }

        @Override
        public void onSdcardFormatFail() {
            LogUtils.d(TAG, "operate_callback: onSdcardFormatFail");
        }

        @Override
        public void onOperationUnknown() {
            LogUtils.d(TAG, "operate_callback: onOperationUnknown");
        }
    };

    // TODO: 2023/6/14 dvr相关错误状态回调是否需要弹窗？
    private final IDvrAPI.IDvrStateWatcher mDvrStateWatcher = new IDvrAPI.IDvrStateWatcher() {

        @Override
        public void onDvrStateInitializing() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateInitializing");
            doDvrStateNormal();
        }

        @Override
        public void onDvrStateCapturePic() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateCapturePic");
            doDvrStateNormal();
        }

        @Override
        public void onDvrStateGeneralRecording() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateGeneralRecording");
            doDvrStateNormal();
            doOnRecordStarted(Constants.DvrRecordingType.GENERAL);
        }

        @Override
        public void onDvrStateGeneralRecordPause() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateGeneralRecordPause");
            doDvrStateNormal();
            doOnRecordFinished(Constants.DvrRecordingType.GENERAL, true);
        }

        @Override
        public void onDvrStateEmergencyRecording() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateEmergencyRecording");
            doDvrStateNormal();
            doOnRecordStarted(Constants.DvrRecordingType.EMERGENCY);
        }

        @Override
        public void onDvrStateCameraConnectionLost() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateCameraConnectionLost");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_CAMERA_CONNECTION_LOST);
        }

        @Override
        public void onDvrStateVideoRecordFailure() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateVideoRecordFailure");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_VIDEO_RECORD_FAILURE);
        }

        @Override
        public void onDvrStateNetworkAbnormal() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateNetworkAbnormal");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_NETWORK_ABNORMAL);
        }

        @Override
        public void onDvrStateAccelerationSensorAbnormal() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateAccelerationSensorAbnormal");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_ACCELERATION_SENSOR_ABNORMAL);
        }

        @Override
        public void onDvrStateMemoryReadError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateMemoryReadError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_MEMORY_READ_ERROR);
        }

        @Override
        public void onDvrStateMemoryWriteError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateMemoryWriteError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_MEMORY_WRITE_ERROR);
        }

        @Override
        public void onDvrStateSystemError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateSystemError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_SYSTEM_ERROR);
        }

        @Override
        public void onDvrState360ViewsModuleError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrState360ViewsModuleError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_360_VIEWS_MODULE_ERROR);
        }

        @Override
        public void onDvrStateOverHead() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateOverHead");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_OVER_HEAT);
        }

        @Override
        public void onDvrStateResourceOccupied() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateResourceOccupied");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_RESOURCE_OCCUPIED);
        }

        @Override
        public void onDvrStateSdcardStatusPoorWritePerformance() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateSdcardStatusPoorWritePerformance");
            doDvrStateError(DvrEvent.DvrErrorState.SDCARD_STATUS_POOR_WRITE_PERFORMANCE);
        }

        @Override
        public void onDvrStateVoltageAbnormal() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateVoltageAbnormal");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_VOLTAGE_ABNORMAL);
        }

        @Override
        public void onDvrStateUnknownError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateUnknownError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_UNKNOWN_ERROR);
        }

        @Override
        public void onDvrStateEmergencyRecordEnd() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrStateEmergencyRecordEnd");
            doDvrStateNormal();
            doOnRecordFinished(Constants.DvrRecordingType.EMERGENCY, true);
        }

        @Override
        public void onDvrEMMCStateNormal() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrEMMCStateNormal");
            doDvrStateNormal();
        }

        @Override
        public void onDvrEMMCStateError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrEMMCStateError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_EMMC_STATUS_ERROR);
        }

        @Override
        public void onDvrNoError() {
            LogUtils.d(TAG, "dvr_state_callback: onDvrNoError");
            doDvrStateError(DvrEvent.DvrErrorState.DVR_STATE_NO_ERROR);
        }

    };

    // TODO: 2023/6/14 sdcard相关错误状态回调是否需要提示？
    private final IDvrAPI.ISdcardStateWatcher mSdCardStateWatcher = new IDvrAPI.ISdcardStateWatcher() {

        @Override
        public void onSdcardStateUnknown() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateUnknown");
        }

        @Override
        public void onSdcardStateNormal() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateNormal");
        }

        @Override
        public void onSdcardStateNoSdcard() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateNoSdcard");
        }

        @Override
        public void onSdcardStateError() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateError");
        }

        @Override
        public void onSdcardStateInitializeFail() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateInitializeFail");
        }

        @Override
        public void onSdcardStatePoorWritePerformance() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStatePoorWritePerformance");
        }

        @Override
        public void onSdcardStateNotFormatted() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateNotFormatted");
        }

        @Override
        public void onSdcardStateFormatting() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateFormatting");
        }

        @Override
        public void onSdcardStateNoSpace() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateNoSpace");
        }

        @Override
        public void onSdcardStateWriteFail() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateWriteFail");
        }

        @Override
        public void onSdcardStateSdcardIncompatible() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateSdcardIncompatible");
        }

        @Override
        public void onSdcardStateEmergencyAreaOverThreshold() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStateEmergencyAreaOverThreshold");
        }

        @Override
        public void onSdcardStatePrivateFilesTakeTooMuchSpace() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdcardStatePrivateFilesTakeTooMuchSpace");
        }

        @Override
        public void onSdCardStateEmergencyVideoPartitionFull() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdCardStateEmergencyVideoPartitionFull");
        }

        @Override
        public void onSdCardStatePhotoPartitionFull() {
            LogUtils.d(TAG, "sdcard_state_callback: onSdCardStatePhotoPartitionFull");
        }
    };

    private final RecordingTimerHelper mRecordingTimerHelper = new RecordingTimerHelper(Constants.FacingType.EXTERIOR);

    /**
     * 开始监听
     */
    public void start() {
        DvrManager.get().registerDvrStateWatcher(mDvrStateWatcher);
        DvrManager.get().registerOperateResultsWatcher(mOperateResultWatcher);
        DvrManager.get().registerSdcardStateWatcher(mSdCardStateWatcher);
    }

    /**
     * 停止监听
     */
    public void stop() {
        DvrManager.get().unregisterDvrStateWatcher(mDvrStateWatcher);
        DvrManager.get().unregisterOperateResultsWatcher(mOperateResultWatcher);
        DvrManager.get().unregisterSdcardStateWatcher(mSdCardStateWatcher);
    }

    /**
     * 录制开始的处理
     * @param recordingType
     */
    private void doOnRecordStarted(@Constants.DvrRecordingType int recordingType) {
        LiveEventBus.get(DvrEvent.RecordingStartedEvent.class).post(new DvrEvent.RecordingStartedEvent(recordingType));
        // 开始Dvr录像计时
        mRecordingTimerHelper.start();
        if (recordingType == Constants.DvrRecordingType.GENERAL) {
            ConfigManager.getInstance().setExteriorGeneralRecording(true);
        }
    }

    /**
     * 录制结束的处理
     * @param recordingType
     * @param success
     */
    private void doOnRecordFinished(@Constants.DvrRecordingType int recordingType, boolean success) {
        LiveEventBus.get(DvrEvent.RecordingEndedEvent.class).post(new DvrEvent.RecordingEndedEvent(recordingType, success));
        // 停止Dvr录像计时
        mRecordingTimerHelper.stop();
        if (recordingType == Constants.DvrRecordingType.GENERAL) {
            ConfigManager.getInstance().setExteriorGeneralRecording(false);
        }
    }

    /**
     * Dvr状态正常的处理
     */
    private void doDvrStateNormal() {
        LiveEventBus.get(DvrEvent.DvrStateErrorEvent.class).post(new DvrEvent.DvrStateErrorEvent(false));
    }

    /**
     * Dvr状态异常的处理
     * @param dvrErrorState
     */
    private void doDvrStateError(@DvrEvent.DvrErrorState int dvrErrorState) {
        LiveEventBus.get(DvrEvent.DvrStateErrorEvent.class).post(new DvrEvent.DvrStateErrorEvent(true, dvrErrorState));
    }
}
